package com.aliyun.heiyu.powermaster.server.strategy.analyzer;


import com.aliyun.heiyu.common.util.PropertiesUtil;
import com.aliyun.heiyu.common.util.StringUtil;
import com.aliyun.heiyu.powermaster.proto.DeviceInfo;
import com.aliyun.heiyu.powermaster.proto.PowerStrategy;
import com.aliyun.heiyu.powermaster.proto.StrategyAction;
import com.aliyun.heiyu.powermaster.proto.StrategyDetail;
import com.aliyun.heiyu.powermaster.server.strategy.StrategyMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class StrategyAnalyzer {
    private static Logger logger = LoggerFactory.getLogger(StrategyAnalyzer.class);

    protected static Double MAX_POWER_USAGE = 0.95;
    protected static Double MIN_POWER_USAGE = 0.70;
    protected static Double CPU_USAGE = 95.0;
    protected static Double CPU_FREQ_USAGE = 0.95;

    protected StrategyMonitor monitor;
    private String analyzeType;
    private String actionType;
    private Map<String, StrategyAction> sn2Action = new HashMap<>();

    public String getAnalyzeType() {
        return analyzeType;
    }

    public StrategyAnalyzer(String analyzeType, String actionType) {
        this.monitor = new StrategyMonitor();
        this.analyzeType = analyzeType;
        this.actionType = actionType;
        double a = StringUtil.convertDouble(PropertiesUtil.getValue("aiControllerConfig.properties", "max_power_usage"));
        double b = StringUtil.convertDouble(PropertiesUtil.getValue("aiControllerConfig.properties", "min_power_usage"));
        double c = StringUtil.convertDouble(PropertiesUtil.getValue("aiControllerConfig.properties", "cpu_usage"));
        double d = StringUtil.convertDouble(PropertiesUtil.getValue("aiControllerConfig.properties", "cpu_freq_usage"));
        MAX_POWER_USAGE = 0 == a ? MAX_POWER_USAGE : a;
        MIN_POWER_USAGE = 0 == b ? MIN_POWER_USAGE : b;
        CPU_USAGE = 0 == c ? CPU_USAGE : c;
        CPU_FREQ_USAGE = 0 == d ? CPU_FREQ_USAGE : d;
    }

    /**
     * 与前一个时刻的缓存进行对比，避免动作命令的重复
     */
    public Map<String, StrategyAction> getChangedSN2Action(List<StrategyDetail> strategies) {
        //result
        Map<String, StrategyAction> result = getSN2Action(strategies);
        //newSN2Action
        Map<String, StrategyAction> newSN2Action = new HashMap<>();
        newSN2Action.putAll(result);

        for (String sn : sn2Action.keySet()) {
            StrategyAction action = sn2Action.get(sn);
            //设备没有了对应的动作
            if (!result.keySet().contains(sn)) {
                Boolean aTrue = isTrue(sn);
                if(aTrue == null || aTrue){
                    StrategyAction.Builder builder = StrategyAction.newBuilder().mergeFrom(action);
                    builder.setActionName(PowerStrategy.NONE.name());
                    newSN2Action.put(sn, builder.build());
                    result.put(sn, builder.build());
                }
            }
        }
        sn2Action = newSN2Action;

        return result;
    }

    /**
     * 判断当前时刻哪些设备应该执行什么动作
     */
    private Map<String, StrategyAction> getSN2Action(List<StrategyDetail> strategies) {
        Map<String, StrategyAction> sn2Action1 = new HashMap<>();
        for (StrategyDetail strategyDetail : strategies) {
            //动作过滤
            String controlLevel = strategyDetail.getControlLevel();
            List<StrategyAction> strategyActions = strategyDetail.getStrategyActionsList();
            List<StrategyAction> strategyActionList = new ArrayList<>();
            for (StrategyAction strategyAction : strategyActions) {
                if (analyzeType.equals(strategyAction.getActionName())) {
                    strategyActionList.add(strategyAction);
                    break;
                }
            }
            if (strategyActionList.size() <= 0) {
                continue;
            }
            List<DeviceInfo> deviceInfos = strategyDetail.getDeviceInfosList();
            if (deviceInfos.size() <= 0) {
                continue;
            }
            //sn2Action（ActionName字段有改动）
            StrategyAction action = strategyActionList.get(0);//限定一个策略对于一种动作只能有一个
            for (DeviceInfo deviceInfo : deviceInfos) {
                if(!"server".equals(deviceInfo.getDeviceType())){
                    continue;
                }
                StrategyAction.Builder builder = StrategyAction.newBuilder().mergeFrom(action);
                String sn = deviceInfo.getEquipmentNumber();
                Boolean act = monitorCondition(action, sn, controlLevel);
                //判断当前进行什么动作
                if (act != null) {
                    //动作；act为null不动作
                    if (act) {
                        builder.setActionName(actionType);
                    } else {
                        builder.setActionName(PowerStrategy.NONE.name());
                    }
                } else {
                    builder.setActionName(PowerStrategy.DEFAULT.name());
                }
                sn2Action1.put(sn, builder.build());
            }
        }
        return sn2Action1;
    }

    //true:进行动作， false：进行反向动作，null:不进行任何动作
    protected abstract Boolean monitorCondition(StrategyAction strategyAction, String sn, String level);

    //得到现在设备的该动作状态是否开启
    //目的是 -- 从策略中移除走的设备，新增关闭策略中执行的动作
    protected abstract Boolean isTrue(String sn);

}
